package pfa.generator;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.jdom.JDOMException;
import org.omg.CORBA.portable.ValueOutputStream;

import pfa.bo.Etudiant;
import pfa.exceptions.AlormException;
import pfa.exceptions.NotFoundType;
import pfa.exceptions.ObjectNotFound;
import pfa.exceptions.RegleException;
import pfa.utils.AlormUtils;

public class SqlStatementsGenerator {

	private boolean cascade = false;
	private List<Class> listClassPer;

	public SqlStatementsGenerator(DBschemaGenerator dBschemaGenerator) {

		listClassPer = dBschemaGenerator.getListClassPer();

	}

	public String getSaveStatement(Object obj) throws AlormException {
		try {
			Class objClass = obj.getClass();
			if (!listClassPer.contains(objClass))
				throw new ObjectNotFound("l'objet a inserer et non valide !!");

			String objClassName = AlormUtils.getClassName(objClass);
			Field fields[] = objClass.getDeclaredFields();
			String reqPart1 = "";
			String reqPart2 = "";
			Method method;
			Object val;
			for (int i = 1; i < fields.length; i++) {
				if (!fields[i].getType().equals(ArrayList.class)) {
					reqPart1 = reqPart1 + " " + fields[i].getName() + ",";
					String getterM = AlormUtils.getGetterMethod(fields[i]
							.getName());

					method = objClass.getMethod(getterM);
					val = method.invoke(obj);
					if (!listClassPer.contains(fields[i].getType())) {
						if (val.getClass().equals(String.class))
							val = "'" + val + "'";
						
					} else {
						val = null;
					}
					reqPart2 = reqPart2 + " " + val + ",";
				}

			}
			String req = "INSERT INTO " + objClassName + "(" + reqPart1 + ")"
					+ " VALUES (" + reqPart2 + ")";
			System.out.println(req);
		} catch (Exception e) {
			throw new AlormException(e);
		}

		return null;
	}

	public String getDeleteStatement(Object pObject) throws AlormException {
		StringBuilder strb = new StringBuilder();

		if (!cascade) {
			Class lClass = pObject.getClass();
			Method method = null;
			String tableName = AlormUtils.getClassName(lClass);
			String pkName = AlormUtils.getPkName(lClass);
			String getterMethod = AlormUtils.getGetterMethod(pkName);
			Number number = null;
			try {

				method = lClass.getMethod(getterMethod);
				number = (Number) method.invoke(pObject);

			} catch (Exception e) {
				throw new AlormException("an error has occured due to : ", e);
			}

			strb.append("delete from ");
			strb.append(tableName);
			strb.append(" where ");
			strb.append(pkName);
			strb.append("=");
			strb.append(String.valueOf(number));
		}

		return strb.toString();

	}

	public String getUpdateStatement(Object pObject) throws AlormException {
		StringBuilder strb = new StringBuilder("update ");
		Class lClass = pObject.getClass();
		String[] fieldsName = AlormUtils.getAllFieldsName(lClass);
		Map<String, String> map = null;
		String tableName = AlormUtils.getClassName(lClass);
		Method method = null;
		String pkName = AlormUtils.getPkName(lClass);
		String getterMethod = AlormUtils.getGetterMethod(pkName);
		Number number = null;
		try {
			map = AlormUtils.getAllFieldsValue(pObject);
			method = lClass.getMethod(getterMethod);
			number = (Number) method.invoke(pObject);
		} catch (Exception e) {

			throw new AlormException("An error occured :", e);
		}

		strb.append(tableName);
		strb.append(" SET ");

		for (Map.Entry<String, String> entry : map.entrySet()) {

			strb.append(entry.getKey() + "=" + entry.getValue() + "  , ");

		}

		strb.deleteCharAt(strb.length() - 2);
		strb.append(" where ");
		strb.append(pkName);
		strb.append("=");
		strb.append(String.valueOf(number));
		return strb.toString();
	}

	public boolean isCascade() {
		return cascade;
	}

	public void setCascade(boolean cascade) {
		this.cascade = cascade;
	}

}
